/******************************************
MODULO: sig_between_brothers.c
SCOPO: il figlio 1 invia un segnale al 
figlio 2 passando per il padre.
******************************************/
#include <stdio.h>
#include <limits.h>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>

/* 
	funzione per la gestione del segnale. 
	Viene chiamata dalla funzione signal.
*/
void hup_handler(int s)
{
	printf ("**SIGNAL**: Ho ricevuto il segnale numero %d",s);
	if (s==SIGUSR1)
		printf(" dal figlio 1, spero!\n");
	else
		printf(" dal figlio 2, spero!\n");
}

int son1(){
    signal(SIGUSR2, hup_handler);
    printf("Figlio 1: mi sono registrato per catturare SIGUSR2. Dormo 1 s...\n");
    sleep(1);
    
    printf("Figlio 1: sto per inviare SIGUSR1 a figlio 2 passando per il padre\n");
    
    kill(getppid(), SIGUSR1);
    printf("Figlio 1: mi metto in attesa per ricevere SIGUSR2\n");
    pause();
    printf("Figlio 1: ho ricevuto SIGUSR2, muoio\n");
    return 0;
    
}

int son2(){
    signal(SIGUSR1, hup_handler);
    printf("Figlio 2: mi sono registrato per catturare SIGUSR1.\n");
    
    printf("Figlio 2: mi metto in attesa per ricevere SIGUSR1\n");
    pause();
    
    printf("Figlio 2: ho ricevuto SIGUSR1\n");
    
    printf("Figlio 2: sto per inviare SIGUSR2 a figlio 1 passando per il padre\n");
    
    kill(getppid(), SIGUSR2);
    
    printf("Figlio 2: muoio\n");
    return 0;
}

int father(pid_t pid1, pid_t pid2){
    signal(SIGUSR1, hup_handler);
    signal(SIGUSR2, hup_handler);
    
    printf("Padre: mi sono registrato per catturare SIGUSR1 e SIGUSR2\n");
    
    printf("Padre: attendo un segnale (spero SIGUSR1 da figlio 1)\n");
    pause();
    
    printf("Padre: ho ricevuto un SIGUSRx (spero da figlio 1)\n");
    printf("Padre: invio SIGUSR1 a figlio 2\n");
    
    kill(pid2, SIGUSR1);
    
    printf("Padre: attendo un segnale (spero SIGUSR2 da figlio 2)\n");
    pause();
    
    printf("Padre: ho ricevuto un SIGUSRx (spero da figlio 2)\n");
    printf("Padre: invio SIGUSR2 a figlio 1\n");
    kill(pid1, SIGUSR1);
    
    printf("Padre: attendo la terminazione dei figli\n");
    
    wait(NULL);
    wait(NULL);
    printf("Padre: muoio\n");
    return 0;
}


int main (int argc, char **argv)
{
	pid_t pid1, pid2;
	
	pid1 = fork();
	
	if(pid1 == -1){
	    perror("fork() figlio 1");
	    exit(1);
	}else if(pid1 == 0){
	    return son1();
	}else{
	    pid2 = fork();
	    if(pid2 == -1){
	        perror("fork() figlio 2");
	        exit(1);
	    }else if(pid2 == 0){
	        return son2();
	    }else{
	        return father(pid1, pid2);
	    }
	}
	
	exit(0);	
}
